package cn.linstudy.base;

import cn.linstudy.date.DateUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @Author XiaoLin
 * @Date 2021/7/8 14:43
 * @Description 一些基本的字符串,集合,数字等校验工具
 */
public class ValidatorsUtils {


  /**
   * 简体中文的正则表达式。
   */
  private static final String REGEX_SIMPLE_CHINESE = "^[\u4E00-\u9FA5]+$";

  /**
   * 字母数字的正则表达式。
   */
  private static final String REGEX_ALPHANUMERIC = "[a-zA-Z0-9]+";

  /**
   * 整数或浮点数的正则表达式。
   */
  private static final String REGEX_NUMERIC = "(\\+|-){0,1}(\\d+)([.]?)(\\d*)";

  /**
   * 身份证号码的正则表达式。
   */
  private static final String REGEX_ID_CARD = "(\\d{14}|\\d{17})(\\d|x|X)";

  /**
   * 电子邮箱的正则表达式。
   */
  private static final String REGEX_EMAIL = ".+@.+\\.[a-z]+";

  /**
   * 判断字符串是否只包含字母和数字.
   * @param str 字符串
   * @return 如果字符串只包含字母和数字, 则返回 true, 否则返回 false.
   */
  public static boolean isAlphanumeric(String str) {
    return isRegexMatch(str, REGEX_ALPHANUMERIC);
  }

  /**
   * 判断字符串是否为空.
   * @param str 字符串
   * @return 如果没有字符串会返回false，如果为空返回true.
   */
  public static boolean isBlank(String str) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
      return true;
    }
    for (int i = 0; i < strLen; i++) {
      if ((Character.isWhitespace(str.charAt(i)) == false)) {
        return false;
      }
    }
    return true;
  }

  /**
   * 是否是合法的日期字符串(类似格式:2017-03-01是合法的)
   * <p>
   * <pre>
   *   Validators.isBlank(&quot;2017-03-01&quot;)       = true
   *   Validators.isBlank(&quot;2017-0301&quot;)        = false
   * </pre>
   *
   * @param str 日期字符串
   * @return 是true，否则false
   */
  public static boolean isDate(String str) {
    if (isEmpty(str) || str.length() > 10) {
      return false;
    }

    String[] items = str.split("-");
    if (items.length != 3) {
      return false;
    }
    if (!isNumber(items[0], 1900, 9999) || !isNumber(items[1], 1, 12)) {
      return false;
    }

    int year = Integer.parseInt(items[0]);
    int month = Integer.parseInt(items[1]);

    return isNumber(items[2], 1, DateUtils.getMaxDayOfMonth(year, month - 1));
  }

  /**
   * 是否是合法的日期时间字符串
   * <p>
   * <pre>
   *   Validators.isDateTime(&quot;2017-03-01 12:03:01&quot;)       = true
   *   Validators.isDateTime(&quot;2017-03-01 12:0301&quot;)        = false
   * </pre>
   *
   * @param str 日期时间字符串
   * @return 是true，否则false
   */
  public static boolean isDateTime(String str) {
    if (isEmpty(str) || str.length() > 20) {
      return false;
    }

    String[] items = str.split(" ");

    if (items.length != 2) {
      return false;
    }

    return isDate(items[0]) && isTime(items[1]);
  }

  /**
   * 判断字符串是否是合法的电子邮箱地址.
   *
   * @param str 字符串
   * @return 是true，否则false
   */
  public static boolean isEmail(String str) {
    return isRegexMatch(str, REGEX_EMAIL);
  }

  /**
   * 当数组为null, 或者长度为0, 或者长度为1且元素的值为null时返回 true.
   *
   * @param args
   * @return true/false
   */
  public static boolean isEmpty(Object[] args) {
    return args == null || args.length == 0 || (args.length == 1 && args[0] == null);
  }

  /**
   * 字符串是否为空，null和空格都算是空
   *
   * @param str 字符串
   * @return true/false
   */
  public static boolean isEmpty(String str) {
    return str == null || str.trim().length() == 0;
  }

  /**
   * 判断集合是否为空。
   *
   * @param <T>        集合泛型
   * @param collection 集合对象
   * @return 当集合对象为 null 或者长度为零时返回 true，否则返回 false。
   */
  public static <T> boolean isEmpty(Collection<T> collection) {
    return collection == null || collection.isEmpty();
  }

  /**
   * 判断Map是否为空
   *
   * @param map Map对象
   * @param <K>
   * @param <V>
   * @return 当Map对象为 null 或者元素为空是返回 true，否则返回 false。
   */
  public static <K, V> boolean isEmptyMap(Map<K, V> map) {
    return map == null || map.isEmpty();
  }

  /**
   * <p>
   * Validating for ID card number.
   * </p>
   *
   * @param str string to be validated
   * @return If the str is valid ID card number return true, otherwise return false.
   */
  public static boolean isIdCardNumber(String str) {
    // 15位或18数字, 14数字加x(X)字符或17数字加x(X)字符才是合法的
    return isRegexMatch(str, REGEX_ID_CARD);
  }

  /**
   * 是否为数字的字符串。
   *
   * @param str 字符串
   * @return true/false
   */
  public static boolean isNumber(String str) {
    if (isEmpty(str)) {
      return false;
    }

    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) > '9' || str.charAt(i) < '0') {
        return false;
      }
    }
    return true;
  }

  /**
   * 是否是固定范围内的数字的字符串
   *
   * @param str
   * @param min
   * @param max
   * @return true/false
   */
  public static boolean isNumber(String str, int min, int max) {
    if (!isNumber(str)) {
      return false;
    }

    int number = Integer.parseInt(str);
    return number >= min && number <= max;
  }

  /**
   * 判断字符是否为整数或浮点数. <br>
   *
   * @param str 字符串
   * @return 若为整数或浮点数则返回 true, 否则返回 false
   */
  public static boolean isNumeric(String str) {
    return isRegexMatch(str, REGEX_NUMERIC);
  }

  /**
   * 判断字符是否为符合精度要求的整数或浮点数。
   *
   * @param str         字符串
   * @param fractionNum 小数部分的最多允许的位数
   * @return 若为整数或浮点数则返回 true, 否则返回 false
   */
  public static boolean isNumeric(String str, int fractionNum) {
    if (isEmpty(str)) {
      return false;
    }

    // 整数或浮点数
    String regex = "(\\+|-){0,1}(\\d+)([.]?)(\\d{0," + fractionNum + "})";
    return Pattern.matches(regex, str);
  }

  /**
   * 判断是否是合法的邮编

   * @param str 字符串
   * @return true/false
   */
  public static boolean isPostcode(String str) {
    if (isEmpty(str)) {
      return false;
    }

    if (str.length() != 6 || !ValidatorsUtils.isNumber(str)) {
      return false;
    }

    return true;
  }

  /**
   * 判断是否是固定长度范围内的字符串
   *
   * @param str
   * @param minLength
   * @param maxLength
   * @return true/false
   */
  public static boolean isString(String str, int minLength, int maxLength) {
    if (str == null) {
      return false;
    }

    if (minLength < 0) {
      return str.length() <= maxLength;
    } else if (maxLength < 0) {
      return str.length() >= minLength;
    } else {
      return str.length() >= minLength && str.length() <= maxLength;
    }
  }

  /**
   * 判断是否是合法的时间字符串。
   *
   * @param str 字符串
   * @return true/false
   */
  public static boolean isTime(String str) {
    if (isEmpty(str) || str.length() > 8) {
      return false;
    }

    String[] items = str.split(":");

    if (items.length != 2 && items.length != 3) {
      return false;
    }

    for (int i = 0; i < items.length; i++) {
      if (items[i].length() != 2 && items[i].length() != 1) {
        return false;
      }
    }

    return !(!isNumber(items[0], 0, 23) || !isNumber(items[1], 0, 59) || (items.length == 3 && !isNumber(items[2],
        0, 59)));
  }

  /**
   * 是否是简体中文字符串。
   *
   * @param str 字符串
   * @return true/false
   */
  public static boolean isSimpleChinese(String str) {
    return isRegexMatch(str, REGEX_SIMPLE_CHINESE);
  }

  /**
   * 判断字符串是否匹配了正则表达式。
   *
   * @param str   字符串
   * @param regex 正则表达式
   * @return true/false
   */
  public static boolean isRegexMatch(String str, String regex) {
    return str != null && str.matches(regex);
  }

  public static void main(String[] args) {
    ArrayList<Object> arrays = new ArrayList<>();
    System.out.println(isEmpty(arrays));
  }


}
